package com.tcfvic.client.panels.widgets;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.tcfvic.client.PersonService;
import com.tcfvic.client.PersonServiceAsync;
import com.tcfvic.client.panels.PersonDetailsForm;
import com.tcfvic.client.panels.widgets.addons.advancedtable.AdvancedTable;
import com.tcfvic.client.panels.widgets.addons.advancedtable.RowSelectionListener;
import com.tcfvic.client.panels.widgets.widgetcontents.CompanyTab;
import com.tcfvic.client.panels.widgets.widgetcontents.EmployStatusTab;
import com.tcfvic.client.panels.widgets.widgetcontents.ExpensesTab;
import com.tcfvic.client.panels.widgets.widgetcontents.JSPTab;
import com.tcfvic.client.panels.widgets.widgetcontents.PersonTab;
import com.tcfvic.client.panels.widgets.widgetcontents.TrainingTab;
import com.tcfvic.client.pojos.Fundingsource;
import com.tcfvic.client.pojos.Person;
import com.tcfvic.client.pojos.Personcourse;
import com.tcfvic.client.pojos.Personfundingsource;
import com.tcfvic.client.pojos.PersonfundingsourceId;
import com.tcfvic.client.tools.Tools;

public class PersonDetailsInputWidget extends DecoratedTabPanel implements
		RowSelectionListener {
	private PersonDetailsListWidget list = null;
	private ListBox multiBoxFundingSourceUnSelected = new ListBox(false);
	private ListBox multiBoxFundingSourceSelected = new ListBox(false);
	private HTML initialFunding = new HTML();
	private HTML availableFunding = new HTML();
	private String currentPersonRowId = "";
	private TCFWidgetContent personTab = new PersonTab();
//	private TCFWidgetContent personBackgroundTab = new PersonBackgroundTab();
	private TCFWidgetContent expensesTab = new ExpensesTab();
	private TCFWidgetContent trainingTab = new TrainingTab();
	private TCFWidgetContent companyTab = new CompanyTab();
	private TCFWidgetContent jspTab = new JSPTab();
//	private TCFWidgetContent edLangTab = new EducationLanguageTab();
	private TCFWidgetContent employStatusTab = new EmployStatusTab();
	private List<TCFWidgetContent> tabs = new ArrayList<TCFWidgetContent>();

	/**
	 * Create a remote service proxy to talk to the server-side PersonDetails
	 * service.
	 */
	private final PersonServiceAsync personService = GWT
			.create(PersonService.class);

	public PersonDetailsInputWidget(PersonDetailsForm personDetailsForm) {
		super();

		initialise();

	}

	public void initialise() {
		super.clear();
		// setWidth("400px");
		setAnimationEnabled(true);
		clear();
		tabs.clear();
		tabs.add(personTab);
//		tabs.add(personBackgroundTab);
//		tabs.add(edLangTab);
		tabs.add(companyTab);
		tabs.add(trainingTab);
		tabs.add(expensesTab);
		tabs.add(jspTab);
		tabs.add(employStatusTab);

		for (TCFWidgetContent tab : tabs) {
			tab.setSaveClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					savePersonDetails();
				}
			});
			add(tab.getContent(), tab.getName());
			tab.initialise();
		}

//		add(createFundingSourceTabContent(), "Funding");
		super.selectTab(0);
	}

	@SuppressWarnings("unused")
	private Widget createFundingSourceTabContent() {
		final Button moveToRight = new Button("->");
		final Button moveToLeft = new Button("<-");

		// Create a table to layout the form options
		FlexTable ft = new FlexTable();
		ft.setCellSpacing(4);
		ft.setWidth("100%");

		HorizontalPanel hPanel = new HorizontalPanel();
		hPanel.setSpacing(20);
		// Add a list box with multiple selection enabled
		multiBoxFundingSourceUnSelected.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				ListBox box = (ListBox) event.getSource();
				if (box.getSelectedIndex() >= 0) {
					moveToRight.setEnabled(true);
				}
			}
		});
		multiBoxFundingSourceUnSelected.ensureDebugId("cwListBox-multiBox");
		multiBoxFundingSourceUnSelected.setWidth("11em");
		multiBoxFundingSourceUnSelected.setVisibleItemCount(10);
		VerticalPanel vertPanel = new VerticalPanel();
		vertPanel.setSpacing(4);
		vertPanel.add(new HTML("Select funding sources:"));
		vertPanel.add(multiBoxFundingSourceUnSelected);
		hPanel.add(vertPanel);
		// Add hpanel to box
		ft.setWidget(0, 0, hPanel);

		// Add buttons
		VerticalPanel buttonsPanel = new VerticalPanel();
		hPanel.setSpacing(10);

		moveToRight.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (multiBoxFundingSourceUnSelected.getSelectedIndex() >= 0) {
					String itemId = multiBoxFundingSourceUnSelected
							.getValue(multiBoxFundingSourceUnSelected
									.getSelectedIndex());
					String itemText = multiBoxFundingSourceUnSelected
							.getItemText(multiBoxFundingSourceUnSelected
									.getSelectedIndex());
					multiBoxFundingSourceUnSelected
							.removeItem(multiBoxFundingSourceUnSelected
									.getSelectedIndex());
					multiBoxFundingSourceSelected.addItem(itemText, itemId);
					moveToRight.setEnabled(false);
					moveToLeft.setEnabled(false);
				}
			}
		});
		moveToRight.ensureDebugId("cwBasicButton-normal");
		moveToRight.setEnabled(false);
		buttonsPanel.add(moveToRight);

		// Add a left click button
		moveToLeft.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (multiBoxFundingSourceSelected.getSelectedIndex() >= 0) {
					String itemId = multiBoxFundingSourceSelected
							.getValue(multiBoxFundingSourceSelected
									.getSelectedIndex());
					String itemText = multiBoxFundingSourceSelected
							.getItemText(multiBoxFundingSourceSelected
									.getSelectedIndex());
					multiBoxFundingSourceSelected
							.removeItem(multiBoxFundingSourceSelected
									.getSelectedIndex());
					multiBoxFundingSourceUnSelected.addItem(itemText, itemId);
					moveToRight.setEnabled(false);
					moveToLeft.setEnabled(false);
				}
			}
		});
		moveToLeft.ensureDebugId("cwBasicButton-disabled");
		moveToLeft.setEnabled(false);
		buttonsPanel.add(moveToLeft);

		// add buttons panel to flex table
		ft.setWidget(0, 1, buttonsPanel);

		hPanel = new HorizontalPanel();
		hPanel.setSpacing(20);
		// Add a list box with multiple selection enabled
		multiBoxFundingSourceSelected.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				moveToLeft.setEnabled(true);
				populateFundingData();
			}
		});
		multiBoxFundingSourceSelected.ensureDebugId("cwListBox-multiBox");
		multiBoxFundingSourceSelected.setWidth("11em");
		multiBoxFundingSourceSelected.setVisibleItemCount(10);
		vertPanel = new VerticalPanel();
		vertPanel.setSpacing(4);
		vertPanel.add(new HTML("Funding assigned:"));
		vertPanel.add(multiBoxFundingSourceSelected);
		hPanel.add(vertPanel);
		// Add hpanel to box
		ft.setWidget(0, 2, hPanel);

		populateSelectedAndUnselectedFS(multiBoxFundingSourceUnSelected,
				multiBoxFundingSourceSelected);

		// create Funding info grid
		Grid grid = new Grid(4, 2);

		// Add images to the grid
		grid.setWidget(0, 0, new HTML("Initial funding"));
		grid.setWidget(0, 1, initialFunding);
		grid.setWidget(1, 0, new HTML("Funding available"));
		grid.setWidget(1, 1, availableFunding);
		grid.ensureDebugId("cwGrid");
		ft.setWidget(0, 3, grid);

		// SAVE button
		final Button saveButton = new Button("Save");
		saveButton.getElement().setId("saveButton");
		ft.setWidget(1, 3, saveButton);

		// Add a handler to close the DialogBox
		saveButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				savePersonDetails();
			}
		});

		return ft;
	}

	private void populateFundingData() {
		if (multiBoxFundingSourceSelected.getSelectedIndex() >= 0) {
			String id = multiBoxFundingSourceSelected
					.getValue(multiBoxFundingSourceSelected.getSelectedIndex());
			personService.getFundingSourceDetails(Integer.valueOf(id),
					new AsyncCallback<Fundingsource>() {

						@Override
						public void onSuccess(Fundingsource result) {
							initialFunding.setText(String.valueOf(result
									.getInitialamount()));
						}

						@Override
						public void onFailure(Throwable caught) {
							System.err
									.println("Error occured getting the funding source details (initial funding amount): "
											+ caught);

						}

					});

			personService.getPersonCourseDetails(Integer
					.valueOf(currentPersonRowId),
					new AsyncCallback<List<Personcourse>>() {

						@Override
						public void onSuccess(List<Personcourse> result) {
							Double cost = 0D;
							for (Personcourse course : result) {
								if (course.getCourse() != null
										&& course.getCourse().getCost() != null
										&& Double.valueOf(course.getCourse()
												.getCost()) > 0) {
									cost += Double.valueOf(course.getCourse()
											.getCost());
								}
							}
							Double available = Double.valueOf(initialFunding
									.getText())
									- cost;
							availableFunding.setText(String.valueOf(available));
						}

						@Override
						public void onFailure(Throwable caught) {
							System.err
									.println("Error occured getting the funding source details (person-course details): "
											+ caught);

						}

					});

		}
	}

	private void populateSelectedAndUnselectedFS(final ListBox unselectedFS,
			final ListBox selectedFS) {
		populateSelectedAndUnselectedFS(unselectedFS, selectedFS,
				new ArrayList<Integer>());

	}

	private void populateSelectedAndUnselectedFS(final ListBox unselectedFS,
			final ListBox selectedFS,
			final Set<Personfundingsource> personFundingSources) {
		List<Integer> ids = new ArrayList<Integer>();
		for (Personfundingsource pfs : personFundingSources) {
			ids.add(pfs.getFundingsource().getId());
		}
		populateSelectedAndUnselectedFS(unselectedFS, selectedFS, ids);
	}

	private void populateSelectedAndUnselectedFS(final ListBox unselectedFS,
			final ListBox selectedFS, final List<Integer> selectedIDs) {

		personService
				.getAllFundingSources(new AsyncCallback<List<Fundingsource>>() {
					@Override
					public void onSuccess(List<Fundingsource> result) {
						Tools.clearList(multiBoxFundingSourceUnSelected,
								multiBoxFundingSourceSelected);
						for (Fundingsource source : result) {
							if (selectedIDs.contains(source.getId())) {
								selectedFS.addItem(source.getSourceName(),
										String.valueOf(source.getId()));
							} else {
								unselectedFS.addItem(source.getSourceName(),
										String.valueOf(source.getId()));
							}
						}

					}

					@Override
					public void onFailure(Throwable caught) {
						Tools.clearList(multiBoxFundingSourceUnSelected,
								multiBoxFundingSourceSelected);
						new SimpleMessagePopup(
								"Error occured getting the funding source list",
								null).showPopup();
						System.err
								.println("Error occured getting the funding source list. "
										+ caught);
					}
				});

	}

	private void savePersonDetails() {
		try {
			Person personDetailsDTO = personTab.saveContent(null);
			if (personDetailsDTO == null) {
				return;
			}
//			personDetailsDTO = personBackgroundTab
//					.saveContent(personDetailsDTO);
			expensesTab.saveContent(personDetailsDTO);
			jspTab.saveContent(personDetailsDTO);
			employStatusTab.saveContent(personDetailsDTO);

			if (Tools.checkIfContainsValues(multiBoxFundingSourceSelected)) {
				Set<Personfundingsource> personFundingSources = new HashSet<Personfundingsource>();
				for (int i = 0; i < multiBoxFundingSourceSelected
						.getItemCount(); i++) {
					Personfundingsource pFS = new Personfundingsource();
					pFS.setId(new PersonfundingsourceId(
							Integer.valueOf(multiBoxFundingSourceSelected
									.getValue(i)), 0));
					personFundingSources.add(pFS);
				}
				personDetailsDTO.setPersonfundingsources(personFundingSources);
			}

			Set<Personcourse> personCourses = trainingTab.saveContent(null);
			personDetailsDTO = companyTab.saveContent(personDetailsDTO);
			if (personDetailsDTO == null) {
				return;
			}

//			personDetailsDTO = edLangTab.saveContent(personDetailsDTO);

			if (personCourses != null && personCourses.size() > 0) {
				personDetailsDTO.setPersoncourses(personCourses);
			}

			personService.savePersonDetails(personDetailsDTO,
					new AsyncCallback<Person>() {
						@Override
						public void onSuccess(Person result) {
							System.out
									.println("Successfully wrote record to dbase");
//							initialise();
							if (list != null) {
								list.updateTableData();
							}
							for (TCFWidgetContent tab : tabs) {
								tab.onSave(result);
							}

							new SimpleMessagePopup("Saved successfully",
									null).showPopup();
						}

						@Override
						public void onFailure(Throwable caught) {
							System.err
									.println("Error occured writing person details to database in "
											+ "PersonDetailsPanel.savePersonDetail: "
											+ caught);
							new SimpleMessagePopup(
									"The data was not saved due to an internal error",
									null).showPopup();
						}
					});
		} catch (Exception e) {
			new SimpleMessagePopup(e.toString(), null)
					.showPopup();
		}
	}

	public void createNewRecord() {
		for (TCFWidgetContent tc : tabs) {
			tc.clear();
			tc.createNewRecord();
		}
	}
	public void clear() {
//		super.clear();
		for (TCFWidgetContent tc : tabs) {
			tc.clear();
		}

		initialFunding.setText("");
		availableFunding.setText("");
		Tools.clearList(multiBoxFundingSourceUnSelected,
				multiBoxFundingSourceSelected);
	}

	public void addPersonList(PersonDetailsListWidget list) {
		this.list = list;
	}

	@Override
	public void onRowSelected(AdvancedTable sender, String rowId) {
		clear();
		currentPersonRowId = rowId;
		personService.getPersonDetails(Integer.valueOf(rowId),
				new AsyncCallback<Person>() {

					@Override
					public void onSuccess(Person result) {
						// populate all tabs in list
						for (TCFWidgetContent tab : tabs) {
							tab.updateContent(result);
						}
						if (result.getPersonfundingsources() != null) {
							populateSelectedAndUnselectedFS(
									multiBoxFundingSourceUnSelected,
									multiBoxFundingSourceSelected, result
											.getPersonfundingsources());

						}
//						personDetailsForm.getvSplit().setSplitPosition("17%");
					}

					@Override
					public void onFailure(Throwable caught) {
						System.err
								.println("Error occured returning the individuals details: "
										+ caught);
						new SimpleMessagePopup(
								"The persons' record was not retrieved due to an internal error",
								null).showPopup();
					}
				});
	}


}
